/**
 * Copyright (C), 2020-2020,贵州铭明网络科技有限公司
 * FileName: AdministratorInfoServiceImpl
 * Author:   杨朝湖
 * Date:     2020/12/8 10:21
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.mm.service.impl;

import com.mm.bo.AdminListBo;
import com.mm.bo.AdminLoginBo;
import com.mm.bo.AdminUpateBo;
import com.mm.bo.InsertAdminInfoBo;
import com.mm.exception.CustomException;
import com.mm.mapper.AdministratorInfoMapper;
import com.mm.mapper.LogsInfoMapper;
import com.mm.org.n3r.idworker.Sid;
import com.mm.pojo.AdministratorInfo;
import com.mm.pojo.LogsInfo;
import com.mm.redis.RedisService;
import com.mm.rediskey.AdminKey;
import com.mm.rediskey.shiro;
import com.mm.service.AdministratorInfoService;
import com.mm.util.*;
import com.mm.vo.AdminListVo;
import com.mm.vo.AdminLoginVo;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;

/**
 * 〈一句话功能简述〉<br>
 * 〈〉
 *
 * @author Gym
 * @create 2020/12/8
 * @since 1.0.0
 */
@Service
public class AdministratorInfoServiceImpl implements AdministratorInfoService {
    @Resource
    private AdministratorInfoMapper administratorInfoMapper;
    @Resource
    private Sid sid;
    @Resource
    private RedisService redisService;
    @Resource
    private LogsInfoMapper logsInfoMapper;

    private static final String password_code = "799359";

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer insertAdminInfo(InsertAdminInfoBo insertAdminInfoBo) throws Exception {
        //获取当前管理员信息
        AdministratorInfo administratorInfoRedis = redisService.get(AdminKey.admin, insertAdminInfoBo.getToken(), AdministratorInfo.class);

        Example example = new Example(AdministratorInfo.class);
        example.createCriteria().andEqualTo("adminName", insertAdminInfoBo.getAdminName());
        AdministratorInfo administratorInfoDB = administratorInfoMapper.selectOneByExample(example);
        if (administratorInfoDB != null) {
            throw new CustomException("已存在当前管理员，请勿重复添加！");
        }

        AdministratorInfo administratorInfo = new AdministratorInfo();
        BeanUtils.copyProperties(administratorInfo, insertAdminInfoBo);
        //获取管理员Id
        String adminId = sid.nextShort();
        administratorInfo.setAdminId(adminId);
        //生成用户的加密盐
        String adminKey = GenerateKeyUtil.getKey();
        administratorInfo.setAdminKey(adminKey);
        //创建管理员的密码信息
        String adminPassword = GenerateKeyUtil.randomPassword(8);
        administratorInfo.setAdminPassword(MD5Util.Encryption(adminPassword, adminKey));
        int rowAdmin = administratorInfoMapper.insertSelective(administratorInfo);
        //获取当前时间戳
        long timeMillis = System.currentTimeMillis();
        //添加日志信息
        //获取日志详情
        String log_detail = "管理员：" + administratorInfoRedis.getAdminRealName() + "添加的新的管理员：" + insertAdminInfoBo.getAdminRealName();
        LogsInfo logsInfo = new LogsInfo(sid.nextShort(), administratorInfoRedis.getAdminId(), log_detail, timeMillis, timeMillis);
        logsInfoMapper.insertSelective(logsInfo);

        //发送短信通知
        SendSmsUtil.sendSmsCode(insertAdminInfoBo.getAdminName(), password_code, adminPassword);
        return rowAdmin;
    }

    @Override
    public AdminLoginVo login(AdminLoginBo adminLoginBo) {
        //获取当前用户是否登录过
        String oldToken = redisService.get(AdminKey.admin, adminLoginBo.getAdminName() + "admin", String.class);
        if (StringUtils.isNotEmpty(oldToken)) {
            redisService.delete(AdminKey.admin, adminLoginBo.getAdminName() + "admin");
            redisService.delete(AdminKey.admin, oldToken);
            redisService.delete(shiro.session, oldToken);
        }
        // 获取管理员信息
        Example example = new Example(AdministratorInfo.class);
        example.createCriteria().andEqualTo("adminName", adminLoginBo.getAdminName());
        // 执行查询方法
        AdministratorInfo administratorInfoDB = administratorInfoMapper.selectOneByExample(example);
        if (administratorInfoDB == null) {
            throw new CustomException("不存在该用户");
        }
        if (administratorInfoDB.getAdminStatus() == 0) {
            throw new CustomException("不存在该用户");
        }
        if (administratorInfoDB.getAdminStatus() == 2) {
            throw new CustomException("账号已被锁定，请联系管理员");
        }
        //1.获取Subject
        Subject subject = SecurityUtils.getSubject();
        //2.封装用户数据
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(adminLoginBo.getAdminName(), adminLoginBo.getAdminPassword());
        //3.执行登录方法
        subject.login(usernamePasswordToken);
        // 获取token
        Subject subjects = SecurityUtils.getSubject();
        Session session = subjects.getSession();
        String token = (String) session.getId();
        //存储用户信息到redis中
        // 验证成功之后把用户信息添加的redis中
        redisService.set(AdminKey.admin, token, administratorInfoDB);
        redisService.set(AdminKey.admin, adminLoginBo.getAdminName() + "admin", token);
        // 处理返回的信息
        AdminLoginVo adminLoginVo = new AdminLoginVo(administratorInfoDB.getAdminName(),
                administratorInfoDB.getAdminRealName(), administratorInfoDB.getAdminBirthday(), administratorInfoDB.getAdminSex(), administratorInfoDB.getAdminEmail(), administratorInfoDB.getAdminHeadPort(), token);
        return adminLoginVo;
    }

    @Override
    public PageUtil<AdminListVo> queryAdminList(AdminListBo adminListBo) {
        AdministratorInfo administratorInfoDB = redisService.get(AdminKey.admin, adminListBo.getToken(), AdministratorInfo.class);
        adminListBo.setAdminId(administratorInfoDB.getAdminId());
        //查询总数
        Integer count = administratorInfoMapper.queryAdminListCount(adminListBo);
        //查询列表信息
        List<AdminListVo> adminListVos = administratorInfoMapper.queryAdminList(adminListBo);
        PageUtil<AdminListVo> page = new PageUtil<>(count, count, adminListBo.getPageIndex(), adminListBo.getPageSize(), adminListVos);
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer updateAdminInfo(AdminUpateBo adminUpateBo) throws Exception {
        //获取当前管理员信息
        AdministratorInfo administratorInfoRedis = redisService.get(AdminKey.admin, adminUpateBo.getToken(), AdministratorInfo.class);
        AdministratorInfo administratorInfo = new AdministratorInfo();
        BeanUtils.copyProperties(administratorInfo, adminUpateBo);
        //执行修改方法
        int rowAdmin = administratorInfoMapper.updateByPrimaryKeySelective(administratorInfo);
        //获取当前时间戳
        long timeMillis = System.currentTimeMillis();
        //获取被修改管理员的信息
        AdministratorInfo administratorInfoDB = administratorInfoMapper.selectByPrimaryKey(adminUpateBo.getAdminId());
        //添加日志信息
        //获取日志详情
        String log_detail = "管理员：" + administratorInfoRedis.getAdminRealName() + "修改了管理员：" + administratorInfoDB.getAdminRealName() + "的基本信息";
        LogsInfo logsInfo = new LogsInfo(sid.nextShort(), administratorInfoRedis.getAdminId(), log_detail, timeMillis, timeMillis);
        logsInfoMapper.insertSelective(logsInfo);
        return rowAdmin;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer resetAdminPassword(String adminId, String token) {
        //获取当前管理员信息
        AdministratorInfo administratorInfoRedis = redisService.get(AdminKey.admin, token, AdministratorInfo.class);
        //查询需要修改管理员的信息
        AdministratorInfo administratorInfo = administratorInfoMapper.selectByPrimaryKey(adminId);
        //获取新的密码信息
        String randomPassword = GenerateKeyUtil.randomPassword(8);
        administratorInfo.setAdminPassword(MD5Util.Encryption(randomPassword, administratorInfo.getAdminKey()));
        //执行修改方法
        int rowAdmin = administratorInfoMapper.updateByPrimaryKeySelective(administratorInfo);
        //添加日志信息
        //获取当前时间戳
        long timeMillis = System.currentTimeMillis();
        //获取日志详情
        String log_detail = "管理员：" + administratorInfoRedis.getAdminRealName() + "重置管理员：" + administratorInfo.getAdminRealName() + "的登录密码";
        LogsInfo logsInfo = new LogsInfo(sid.nextShort(), administratorInfoRedis.getAdminId(), log_detail, timeMillis, timeMillis);
        logsInfoMapper.insertSelective(logsInfo);
        //发送短信验证码通知被重置密码的管理员
        SendSmsUtil.sendSmsCode(administratorInfo.getAdminName(), password_code, randomPassword);
        return rowAdmin;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer deleteAdminInfo(String adminId, String token) {
        //获取当前管理员信息
        AdministratorInfo administratorInfoRedis = redisService.get(AdminKey.admin, token, AdministratorInfo.class);
        //查询需要删除管理员的信息
        AdministratorInfo administratorInfo = administratorInfoMapper.selectByPrimaryKey(adminId);
        administratorInfo.setAdminStatus(0);
        //执行修改方法
        int rowAdmin = administratorInfoMapper.updateByPrimaryKeySelective(administratorInfo);
        //添加日志信息
        //获取当前时间戳
        long timeMillis = System.currentTimeMillis();
        //获取日志详情
        String log_detail = "管理员：" + administratorInfoRedis.getAdminRealName() + "删除了管理员：" + administratorInfo.getAdminRealName() + "的登录账号";
        LogsInfo logsInfo = new LogsInfo(sid.nextShort(), administratorInfoRedis.getAdminId(), log_detail, timeMillis, timeMillis);
        logsInfoMapper.insertSelective(logsInfo);
        return rowAdmin;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer lockingAdminInfo(String adminId, String token) {
        //获取当前管理员信息
        AdministratorInfo administratorInfoRedis = redisService.get(AdminKey.admin, token, AdministratorInfo.class);
        //查询需要删除管理员的信息
        AdministratorInfo administratorInfo = administratorInfoMapper.selectByPrimaryKey(adminId);
        administratorInfo.setAdminStatus(2);
        //执行修改方法
        int rowAdmin = administratorInfoMapper.updateByPrimaryKeySelective(administratorInfo);
        //添加日志信息
        //获取当前时间戳
        long timeMillis = System.currentTimeMillis();
        //获取日志详情
        String log_detail = "管理员：" + administratorInfoRedis.getAdminRealName() + "锁定了管理员：" + administratorInfo.getAdminRealName() + "的登录账号";
        LogsInfo logsInfo = new LogsInfo(sid.nextShort(), administratorInfoRedis.getAdminId(), log_detail, timeMillis, timeMillis);
        logsInfoMapper.insertSelective(logsInfo);
        return rowAdmin;
    }
}